package com.sdy.hospitalguard.h5.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sdy.common.model.BizException;
import com.sdy.common.model.Response;
import com.sdy.common.utils.Assert;
import com.sdy.hospitalguard.biz.constants.RedisConstants;
import com.sdy.hospitalguard.biz.dto.NoticeDto;
import com.sdy.hospitalguard.biz.dto.PersonDataDTO;
import com.sdy.hospitalguard.biz.dto.UpdateNoticeDataDTO;
import com.sdy.hospitalguard.biz.model.HospitalUser;
import com.sdy.hospitalguard.biz.model.Notice;
import com.sdy.hospitalguard.biz.model.VisitAppointment;
import com.sdy.hospitalguard.biz.service.*;
import com.sdy.hospitalguard.biz.utils.CopyUtil;
import com.sdy.mvc.controller.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
 * @author cgj
 * @since 2020/05/09
 */
@RestController
@RequestMapping("/personData")
@Api(tags = "人员信息接口")
@Slf4j
public class PersonDataController extends BaseController {
    @Autowired
    private HospitalUserService hospitalUserService;
    @Autowired
    private NoticeService noticeService;
    @Autowired
    private ApplyPostService applyPostService;
    @Autowired
    private VisitAppointmentService visitAppointmentService;
    @Autowired
    private RedisLockRegistry redisLockRegistry;
    @Autowired
    private EscortAssociatedService escortAssociatedService;

    @GetMapping("/getMyselfData")
    @ApiOperation(value = "获取个人相关信息", response = PersonDataDTO.class)
    public Response getMyselfData(HttpServletRequest request) {
        Integer userId = getUserId(request);
        HospitalUser personData = hospitalUserService.getById(userId);
        PersonDataDTO clonePersonData = CopyUtil.clone(personData, PersonDataDTO.class);
        if (StringUtils.isNotBlank(clonePersonData.getPhone())) {
            String phone = clonePersonData.getPhone();
            String phoneNumber = phone.substring(0, 3) + "****" + phone.substring(7);
            clonePersonData.setPhone(phoneNumber);
        }
        // 我的未查看消息列表
        List<Notice> notices = noticeService.listMyNoticeNew(userId);
        // 未查看消息数量
        int size = notices.size();
        // 此人目前的身份(0-无直接关系 1-患者 2-陪护 3-探视人员 4-陪护+探视)
        Integer identity = applyPostService.checkIdentity(userId);
        clonePersonData.setNumber(size).setIdentity(identity);
        // 头像上传地址
        return Response.success(clonePersonData);
    }

    @GetMapping("/getMyAllNotice")
    @ApiOperation(value = "我的消息列表", response = NoticeDto.class)
    public Response getMyAllNotice(HttpServletRequest request, Page page) {
        Integer userId = getUserId(request);
        // 我的所有消息列表
        IPage<NoticeDto> noticeList = noticeService.pageMyNoticeALL(page, userId);
        List<NoticeDto> noticeDtos = noticeList.getRecords();
        // 如果存在消息才处理
        if (noticeDtos.size() > 0) {
            // 获取我的个人信息
            HospitalUser byId = hospitalUserService.getById(userId);
            String name = byId.getName();
            SimpleDateFormat sdfStart = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            SimpleDateFormat sdfEnd = new SimpleDateFormat("HH:mm");
            ArrayList<Integer> ids = new ArrayList<>();
            for (NoticeDto n : noticeDtos) {
                // 取探视申请的id
                if (n.getType() == 2) {
                    ids.add(n.getAssociationId());
                }
                // 设置是否有权限修改数据
                if (n.getSendUserId().equals(userId)) {
                    n.setHandlePower(2);
                } else {
                    n.setHandlePower(1);
                }
                // 拼接消息内容
                if (n.getType() == 1) {
                    n.setMessageContent(n.getSendUserName() + "向" + n.getHandlerUserName() + "发起陪护关联");
                } else if (n.getType() == 2) {
                    n.setMessageContent(n.getSendUserName() + "向" + n.getHandlerUserName() + "发起探视申请");
                }
                n.setMessageContent(n.getMessageContent().replace(name, "你"));
            }
            // 如果ids不为空才有预约数据
            if (ids.size() > 0) {
                List<VisitAppointment> visitAppointments = visitAppointmentService.listByIds(ids);
                for (int i = 0; i < noticeDtos.size(); i++) {
                    for (int j = 0; j < ids.size(); j++) {
                        if (noticeDtos.get(i).getType() == 2 && noticeDtos.get(i).getAssociationId().equals(visitAppointments.get(j).getId())) {
                            noticeDtos.get(i).setVisitTime(sdfStart.format(visitAppointments.get(j).getVisitStartTime()) + "-"
                                    + sdfEnd.format(visitAppointments.get(j).getVisitEndTime()));
                        }
                    }
                }
            }
        }
        IPage<NoticeDto> noticeDtoIPage = new Page<NoticeDto>()
                .setCurrent(noticeList.getCurrent())
                .setSize(noticeList.getSize())
                .setTotal(noticeList.getTotal())
                .setRecords(noticeDtos);
        // 变成已经阅读
        noticeService.update(Wrappers.<Notice>lambdaUpdate()
                .eq(Notice::getHandlerId, userId).eq(Notice::getState, 1).set(Notice::getState, 2));
        return Response.success(noticeDtoIPage);
    }

    @GetMapping("/getMyAllSendNotice")
    @ApiOperation(value = "我的发送消息列表", response = NoticeDto.class)
    public Response getMyAllSendNotice(HttpServletRequest request, Page page) {
        Integer userId = getUserId(request);
        Page<Notice> noticePage = noticeService.pageMyALLSendNotice(page, userId);
        return Response.success(noticePage);
    }

    @PostMapping("/updateData")
    @ApiOperation(value = "个人消息处理")
    public Response updateData(@RequestBody @ApiParam(value = "updateNoticeDataDTO", name = "UpdateNoticeDataDTO")
                                       UpdateNoticeDataDTO updateNoticeDataDTO) throws BizException, URISyntaxException, InterruptedException {
        Assert.isNull(updateNoticeDataDTO.getId(), "传入id为空！");
        Assert.isNull(updateNoticeDataDTO.getResult(), "尚未告诉我您是否同意！");
        Boolean aBoolean = false;
        // 防止不同患者同时同意成为正在陪护
        Integer id = updateNoticeDataDTO.getId();
        // 个人处理消息
        updateNoticeDataDTO.setDisposeType(0);
        Notice notice = noticeService.getById(id);
        Assert.isNull(notice, "系统正在开小差!");
        // 如果是设置用户成为陪护，则加锁避免超出规则
        if (notice.getType() == 1 && updateNoticeDataDTO.getResult() == 2) {
            Lock lockPatientId = redisLockRegistry.obtain(RedisConstants.LOCK_APPLY_ADDPATIENT_ESCORT +
                    escortAssociatedService.getById(notice.getAssociationId()).getUserId());
            if (!lockPatientId.tryLock(10, TimeUnit.SECONDS)) {
                throw new BizException("该用户被关联次数过于频繁!");
            }
            try {
                aBoolean = noticeService.updateNoticeData(updateNoticeDataDTO.setNotice(notice));
            } finally {
                lockPatientId.unlock();
            }
        } else {
            aBoolean = noticeService.updateNoticeData(updateNoticeDataDTO.setNotice(notice));
        }
        return Response.success(aBoolean);
    }

}
